<template>
  <div class="menu-index">
    <div class="menu-sear" v-show="isHideSear">
      <el-form size="mini" inline>
        <el-form-item label="关键字">
          <el-input
            placeholder="关键字检索(名称/授权标识)"
            v-model="searParams.keyword"
          ></el-input>
        </el-form-item>
        <el-form-item label="菜单能力">
          <el-select
            v-model="searParams.abilityCode"
            size="mini"
            clearable
            placeholder="请选择"
          >
            <el-option
              v-for="item in abilityList"
              :key="item.code"
              :label="item.remark"
              :value="item.code"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="菜单类型">
          <el-select
            v-model="searParams.typeCode"
            size="mini"
            clearable
            placeholder="请选择"
          >
            <el-option
              v-for="item in typeList"
              :key="item.code"
              :label="item.remark"
              :value="item.code"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="创建人">
          <el-select
            v-model="searParams.createBy"
            size="mini"
            clearable
            placeholder="请选择"
          >
            <el-option
              v-for="item in createTenantList"
              :key="item.id"
              :label="item.username"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-button size="mini" type="primary" @click="handleSear"
          >查询</el-button
        >
        <el-button size="mini" @click="handleResetSearParams">重置</el-button>
      </el-form>
    </div>
    <div class="menu-oper">
      <div class="menu-oper-left">
        <el-button
          type="primary"
          size="mini"
          plain
          icon="el-icon-plus"
          @click="handlePreModify"
          >新增</el-button
        >
        <el-button
          type="success"
          size="mini"
          plain
          icon="el-icon-edit"
          @click="handleModifyBatch"
          >修改</el-button
        >
        <el-button
          type="danger"
          size="mini"
          plain
          icon="el-icon-delete"
          @click="handleRemoveBatch"
        >
          删除</el-button
        >
        <el-button
          type="success"
          size="mini"
          plain
          icon="el-icon-download"
          @click="handleExportTemplate"
          >导出模板</el-button
        >
        <el-button
          type="warning"
          size="mini"
          plain
          icon="el-icon-download"
          @click="handleExport"
          >导出</el-button
        >
        <el-button
          type="primary"
          size="mini"
          plain
          icon="el-icon-upload2"
          @click="handleUploadOpen"
          >导入</el-button
        >
        <el-button
          type="danger"
          size="mini"
          plain
          icon="el-icon-refresh"
          @click="handleRefresh"
          >刷新缓存</el-button
        >
        <el-button size="mini" plain icon="el-icon-sort" @click="handleExband"
          >展开/折叠</el-button
        >
      </div>
      <div class="menu-oper-right">
        <el-button
          icon="el-icon-search"
          size="mini"
          circle
          @click="handleHideSear"
        ></el-button>
        <el-button
          icon="el-icon-refresh"
          size="mini"
          @click="handleRefreshPage"
          circle
        ></el-button>
      </div>
    </div>
    <div class="menu-list">
      <el-table
        stripe
        highlight-current-row
        v-if="isRefreshTable"
        :data="menuPage"
        style="width: 100%; margin-bottom: 20px"
        row-key="id"
        :default-expand-all="isExpand"
        tooltip-effect="dark"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"> </el-table-column>
        <!-- <el-table-column prop="id" label="ID" sortable width="180">
      </el-table-column> -->
        <el-table-column prop="name" label="名称" sortable width="150">
        </el-table-column>
        <el-table-column label="菜单类型" width="120" align="center">
          <template slot-scope="scope">
            <el-tag :type="getTypeTag(scope.row.menuType)">{{
              scope.row.menuType.remark
            }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="auth" label="授权标识" width="150">
        </el-table-column>
        <el-table-column prop="auth" label="图标" width="120" align="center">
          <template slot-scope="scope">
            <i
              :class="scope.row.menuMeta != null ? scope.row.menuMeta.icon : ''"
            ></i>
          </template>
        </el-table-column>
        <el-table-column prop="serverUri" label="服务地址" width="150">
        </el-table-column>
        <el-table-column prop="clientUri" label="路由地址" width="150">
        </el-table-column>
        <el-table-column prop="clientPath" label="组件路径" width="150">
        </el-table-column>
        <el-table-column
          prop="ability"
          label="菜单能力"
          width="120"
          align="center"
        >
          <template slot-scope="scope">
            <el-tag
              :type="getAbilityTag(scope.row.menuAbility)"
              effect="plain"
              >{{ scope.row.menuAbility.remark }}</el-tag
            >
          </template>
        </el-table-column>
        <el-table-column
          prop="enable"
          label="是否启用"
          width="150"
          align="center"
        >
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.enable"
              :active-value="1"
              :inactive-value="0"
              active-text="启用"
              inactive-text="禁用"
              @change="handleModifyEnable(scope.row)"
            >
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column
          prop="access"
          label="访问能力"
          width="150"
          align="center"
        >
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.access"
              :active-value="1"
              :inactive-value="0"
              active-color="#67C23A"
              inactive-color="#F56C6C"
              active-text="开放"
              inactive-text="鉴权"
              @change="handleModifyAccess(scope.row)"
            >
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序值" width="150" align="center">
          <template slot-scope="scope">
            <el-input-number
              size="mini"
              v-model="scope.row.sort"
              @change="handleModifySort(scope.row)"
              :max="99"
              :min="0"
            />
          </template>
        </el-table-column>
        <!--         <el-table-column prop="createTime" label="创建时间" width="150">
        </el-table-column>
        <el-table-column prop="updateTime" label="修改时间" width="150">
        </el-table-column> -->
        <el-table-column fixed="right" label="操作" width="120">
          <template slot-scope="scope">
            <el-button @click="handleClick(scope.row)" type="text" size="small"
              >查看</el-button
            >
            <el-button
              type="text"
              size="small"
              @click="handleModifySingle(scope.row)"
              >编辑</el-button
            >
            <el-button
              type="text"
              size="small"
              @click="handleRemoveSingle(scope.row)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
   <!--    <el-pagination
        class="page"
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="menuPage.totalCount"
        :page-sizes="[5, 10, 20, 50]"
        :page-size="menuPage.pageSize"
        @current-change="handleChangeOffset"
        @size-change="handleChangeLimit"
      >
      </el-pagination> -->
    </div>
    <div>
      <el-dialog
        class="dialog"
        title="文件上传"
        :visible.sync="isShowUpload"
        width="26%"
        :before-close="handleUploadClose"
      >
        <el-upload
          :action="fileAttr.action"
          :limit="fileAttr.limit"
          :name="fileAttr.filed"
          :accept="fileAttr.type"
          drag
        >
          <div class="el-upload__text">
            将XML文件拖到此处，或<em>点击上传</em>
          </div>
        </el-upload>
      </el-dialog>
    </div>
    <add-comp
      :types="typeList"
      :abilities="abilityDatum"
      :apis="apiList"
      :renderRule="renderRule"
      :parents="parentList"
      @close="handleCloseAdd"
      @typeUpdate="handleModifyType"
      @submit="handleSubmitAdd"
      v-if="isShowAdd"
    />

    <edit-comp
      :data="updData"
      :types="typeList"
      :abilities="abilityDatum"
      :apis="apiList"
      :renderRule="renderRule"
      :parents="parentList"
      @close="handleCloseEdit"
      @submit="handleSubmitEdit"
      v-if="isShowEdit"
    />
  </div>
</template>

<script>
import { isNotEmpty, isEmpty, isNotNull, isNull } from "@/utils/validate";
import { getTagStr } from "@/utils/menu";
import AddComp from "./addComp.vue";
import EditComp from "./editComp.vue";
export default {
  data() {
    return {
      isExpand: false,
      isRefreshTable: true,
      isHideSear: true,
      isShowUpload: false,
      isShowAdd: false,
      isShowEdit: false,
      searParams: {},
      menuPage: [],
      typeList: [],
      abilityList: [],
      abilityDatum: [],
      createTenantList: [],
      selectItemIds: [],
      selectItems: [],
      fileAttr: {},
      updData: {},
      apiList: [],
      renderRule: {},
      parentList: [],
      currentPanrent: {}
    };
  },
  components: {
    AddComp,
    EditComp,
  },
  created() {
    this.resetSearParams();
    this.list();
    this.getTypes();
    this.getAbility();
    this.getCreateTenant();
  },
  methods: {
    /**
     * 查询菜单类型
     */
    getTypes() {
      this.$store.dispatch("menu/getTypes").then((res) => {
        if (res.code === 0) {
          this.typeList = res.data;
        }
      });
    },
    /**
     * 查询菜单能力
     */
    getAbility() {
      this.$store.dispatch("menu/getAbility").then((res) => {
        if (res.code === 0) {
          this.abilityList = res.data;
        }
      });
    },
    /**
     * 查询菜单创建人
     */
    getCreateTenant() {
      this.$store.dispatch("menu/getCreateTenant").then((res) => {
        if (res.code === 0) {
          this.createTenantList = res.data;
        }
      });
    },
    /**
     * 查询菜单列表
     */
    list() {
      this.$store.dispatch("menu/list", this.searParams).then((res) => {
        if (res.code === 0) {
          this.menuPage = res.data;
          console.log(this.menuPage)
        }
      });
    },
    /**
     *  刷新缓存
     */
    handleRefresh() {
      this.$store.dispatch("menu/refreshCache").then((res) => {
        if (res.code === 0) {
          this.$message({
            message: "刷新缓存成功",
            type: "success",
          });
        } else {
          this.$message.error("刷新缓存失败");
        }
      });
    },
    /**
     * 列表展开或折叠
     */
    handleExband() {
      this.isRefreshTable = false;
      this.isExpand = !this.isExpand;
      this.$nextTick(() => {
        this.isRefreshTable = true;
      });
    },
    /**
     * 隐藏搜索列表
     */
    handleHideSear() {
      this.isHideSear = !this.isHideSear;
    },
    /**
     * 刷新页面
     */
    handleRefreshPage() {
      this.list();
    },
    /**
     * 执行查询
     */
    handleSear() {
      this.list();
    },
    /**
     * 重置搜索参数
     */
    handleResetSearParams() {
      this.resetSearParams();
    },
    /**
     * 设置默认请求参数
     */
    resetSearParams() {
      this.searParams = {
        offset: 1,
        limit: 5,
        abilityCode: "",
        typeCode: "",
        createBy: "",
        keyword: "",
      };
    },
    /**
     * 页码改变
     */
    handleChangeOffset(offset) {
      this.searParams.offset = offset;
      this.list();
    },
    /**
     * 页数改变
     */
    handleChangeLimit(limit) {
      this.searParams.limit = limit;
      this.list();
    },
    /**
     * 复选框选中/取消选中操作
     */
    handleSelectionChange(val) {
      this.selectItemIds = [];
      this.selectItems = [];
      for (let i = 0; i < val.length; i++) {
        this.selectItemIds.push(val[i].id);
        this.selectItems.push(val[i]);
      }
    },
    /**
     * 批量删除
     */
    handleRemoveBatch() {
      this.doRemove(this.selectItemIds);
    },
    /**
     * 单删
     */
    handleRemoveSingle(val) {
      this.doRemove([val.id]);
    },
    /**
     * 执行删除请求
     */
    doRemove(menuIds) {
      if (isEmpty(menuIds)) {
        this.$message("未选中菜单");
        return;
      }
      this.$confirm("此操作将永久删除, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$store.dispatch("menu/removeByIds", menuIds).then((res) => {
            if (res.code === 0) {
              this.list();
              this.$message({
                message: "删除菜单成功",
                type: "success",
              });
            } else {
              this.$message.error("删除菜单失败");
            }
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    /**
     * 排序值改变
     */
    handleModifySort(val) {
      const menu = {
        id: val.id,
        sort: val.sort,
      };
      this.doModify(menu);
    },
    /**
     * 启用/禁用改变
     */
    handleModifyEnable(val) {
      const menu = {
        id: val.id,
        enable: val.enable,
      };
      this.doModify(menu);
    },
    /**
     * 访问能力改变
     */
    handleModifyAccess(val) {
      const menu = {
        id: val.id,
        access: val.access,
      };
      this.doModify(menu);
    },
    /**
     * 执行修改请求
     */
    doModify(menu) {
      this.$store.dispatch("menu/modify", menu).then((res) => {
        if (res.code === 0) {
          this.list();
          this.$message({
            message: "修改菜单成功",
            type: "success",
          });
        } else {
          this.$message.error("修改菜单失败");
        }
      });
    },
    /**
     * 导出菜单
     */
    handleExport() {
      this.$store.dispatch("menu/exportXml", this.selectItemIds).then((res) => {
        if (res.code === 0) {
          this.download(res.data, "menuDatum.xml");
          this.$message({
            message: "导出菜单数据成功",
            type: "success",
          });
        }
      });
    },
    /**
     * 导出菜单模板
     */
    handleExportTemplate() {
      this.$store.dispatch("menu/exportTemplate").then((res) => {
        this.download(res, "menuTemplate.xml");
        this.$message({
          message: "导出菜单模板成功",
          type: "success",
        });
      });
    },
    /**
     * 关闭文件上传
     */
    handleUploadClose() {
      this.isShowUpload = false;
    },
    /**
     * 开发文件上传
     */
    handleUploadOpen() {
      this.fileAttr = {
        action: "http://localhost:9090/sys/menu/import/xml",
        filed: "menuXmlFile",
        limit: 1,
        type: ".xml",
      };
      this.isShowUpload = true;
    },
    /**
     * 下载操作
     */
    download(data, filename) {
      let url = window.URL.createObjectURL(
        new Blob([data], { type: "text/xml" })
      );
      let link = document.createElement("a");
      link.style.display = "none";
      link.href = url;
      link.setAttribute("download", filename);
      document.body.appendChild(link);
      link.click();
    },
    /**
     * 打开添加对话框
     */
    handlePreModify() {
      this.isShowAdd = true;
      this.getApis();
      this.getRenderRule(this.typeList[0].code);
      this.getSupportParent(this.typeList[0].code);
    },
    /**
     * 单个修改
     */
    handleModifySingle(menuData) {
      this.preModify([menuData]);
    },
    /**
     * 选中修改
     */
    handleModifyBatch() {
      this.preModify(this.selectItems);
    },
    /**
     * 打开修改对话框
     */
    preModify(menuDatum) {
      if (menuDatum == null || menuDatum.length != 1) {
        this.$message({
          message: "请选择一个菜单",
          type: "warning",
        });
        return;
      }
      const menuId = menuDatum[0].id;
      this.$store.dispatch("menu/getById", menuId).then((res) => {
        if (res.code === 0) {
          this.updData = res.data;
          this.getApis();
          this.getRenderRule(this.updData.menuType.code);
          this.getSupportParent(this.updData.menuType.code);
          this.getAbilityByTypeCode(this.updData.menuType.code);
          this.isShowEdit = true;
          console.log(this.updData);
        } else {
          this.$message.error("同步菜单数据失败");
        }
      });
    },
    /**
     * 提交修改
     */
    handleSubmitEdit(menuFrom) {
      this.doModify(menuFrom);
      this.isShowEdit = false;
    },
    /**
     * 菜单类型改变
     */
    handleModifyType(typeCode) {
      this.getAbilityByTypeCode(typeCode);
      this.getRenderRule(typeCode);
      this.getSupportParent(typeCode);
    },
    /**
     * 关闭创建对话框
     */
    handleCloseAdd() {
      this.isShowAdd = false;
    },
    /**
     * 关闭修改对话框
     */
    handleCloseEdit() {
      this.isShowEdit = false;
    },
    /**
     * 提交创建
     */
    handleSubmitAdd(menuFrom) {
      this.$store.dispatch("menu/create", menuFrom).then((res) => {
        if (res.code === 0) {
          this.$message({
            message: "创建菜单成功",
            type: "success",
          });
          this.isShowAdd = false;
          this.list();
        } else {
          this.$message.error(res.msg);
        }
      });
    },
    /**
     * 通过菜单类型查询支持的父菜单
     */
    getSupportParent(typeCode) {
      this.$store.dispatch("menu/getSupportParent", typeCode).then((res) => {
        if (res.code === 0) {
          this.parentList = res.data;
        }
      });
    },
    /**
     * 通过菜单类型查询菜单能力
     */
    getAbilityByTypeCode(typeCode) {
      this.$store
        .dispatch("menu/getAbilityByTypeCode", typeCode)
        .then((res) => {
          if (res.code === 0) {
            this.abilityDatum = res.data;
          }
        });
    },
    /**
     * 查询接口列表
     */
    getApis() {
      this.$store.dispatch("menu/getApis").then((res) => {
        if (res.code === 0) {
          this.apiList = res.data;
        }
      });
    },
    /**
     * 查询接口列表
     */
    getRenderRule(typeCode) {
      this.$store.dispatch("menu/getRenderRule", typeCode).then((res) => {
        if (res.code === 0) {
          this.renderRule = res.data;
        }
      });
    },
    /**
     * 获取菜单类型tag样式
     */
    getTypeTag(type) {
      if (!type) return "";
      return getTagStr(type.code, this.typeList.length);
    },
    /**
     * 获取菜单能力tag样式
     */
    getAbilityTag(ability) {
      if (!ability) return "";
      return getTagStr(ability.code, this.abilityList.length);
    }
  },
};
</script>

<style >
.menu-index {
  height: auto;
  margin: 1%;
  display: flex;
  flex-direction: column;
}

.menu-list {
  text-align: center;
}
.menu-oper {
  margin: 12px 0 12px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.menu-oper-left {
  display: flex;
}

.menu-upload {
  padding: 0 10px 0 10px;
}
</style>
